//
// Created by Michael Xu on 7/20/14.
// Copyright (c) 2014 podrow. All rights reserved.
//

#import "NMRowBase.h"

@implementation NMRowBase

+ (NSString*)doCipher:(NSString*)plainText key:(NSString *)key operation:(CCOperation)encryptOrDecrypt
{
    const void *vplainText;
    size_t plainTextBufferSize;

    if (encryptOrDecrypt == kCCDecrypt) {
        NSData *EncryptData = [NSData dataFromBase64String:plainText];
        plainTextBufferSize = [EncryptData length];
        vplainText = [EncryptData bytes];
    } else {
        plainTextBufferSize = [[plainText dataUsingEncoding:NSUTF8StringEncoding] length];
        vplainText = (const void *) [plainText UTF8String];
    }

    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;

    uint8_t iv[kCCBlockSize3DES];
    memset((void *) iv, 0x00, (size_t) sizeof(iv));

    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);

    NSData *testData = [self md5DataFromString:key];
    const char *constSource = [testData bytes];

    unsigned char source[24];
    memcpy(source, constSource, sizeof (source));

    for (int j = 0, k = 16; j < 8;) {
        source[k++] = source[j++];
    }

    ccStatus = CCCrypt(encryptOrDecrypt,
            kCCAlgorithm3DES,
            kCCOptionPKCS7Padding,
            source,
            kCCKeySize3DES,
            iv,
            vplainText,
            plainTextBufferSize,
            (void *)bufferPtr,
            bufferPtrSize,
            &movedBytes);
    if (ccStatus == kCCSuccess) {
#if DEBUG
        NSLog(@"SUCCESS");
#endif
    }
    else if (ccStatus == kCCParamError) {
        return @"PARAM ERROR";
    }
    else if (ccStatus == kCCBufferTooSmall) {
        return @"BUFFER TOO SMALL";
    }
    else if (ccStatus == kCCMemoryFailure) {
        return @"MEMORY FAILURE";
    }
    else if (ccStatus == kCCAlignmentError) {
        return @"ALIGNMENT";
    }
    else if (ccStatus == kCCDecodeError) {
        return @"DECODE ERROR";
    }
    else if (ccStatus == kCCUnimplemented) {
        return @"UNIMPLEMENTED";
    }

    NSString *result;

    if (encryptOrDecrypt == kCCDecrypt) {
        result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding];
    } else {
        NSData *data = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
        result = [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    }
    return result;
}

+ (NSData *)md5DataFromString:(NSString *)input
{
    const char *cStr = [input UTF8String];
    unsigned char digest[16];
    CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call

    return [NSData dataWithBytes:digest length:CC_MD5_DIGEST_LENGTH];
}

@end